package com.yunshipei.core.manager;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import com.yunshipei.core.R;
import com.yunshipei.core.common.XCloudException;
import com.yunshipei.core.net.ServiceApi;
import com.yunshipei.core.utils.FileUtils;
import com.yunshipei.core.utils.YspLogUtils;

import org.json.JSONObject;
import org.reactivestreams.Publisher;

import java.io.File;

import io.reactivex.Flowable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Response;

final class KernelHandler {

    private static final String kernelFileName = "libxwalkcore.so";
    private static final String KERNEL_MD5 = "xcloud.kernel.md5";

    private Context context;
    private String kernelFilePath;
    private ServiceApi serviceApi;
    private String managerServer;
    private SharedPreferences preferences;

    KernelHandler(Context context, String managerServer,String kernelFilePath, ServiceApi serviceApi) {
        this.context = context;
        this.managerServer = managerServer;
        this.kernelFilePath = kernelFilePath;
        this.serviceApi = serviceApi;
        this.preferences = context.getSharedPreferences(XCloudSDKManager.SP_CONFIG_FILE_NAME, Context.MODE_PRIVATE);
    }

    Flowable<Boolean> prepareKernel() {
        return serviceApi.kernelInfo().flatMap(new Function<JSONObject, Publisher<Boolean>>() {
            @Override
            public Publisher<Boolean> apply(JSONObject jsonObject) throws Exception {
                String md5 = jsonObject.optString("md5", "");
                String downloadUrl = jsonObject.optString("downloadUrl", "");
                String oldMd5 = preferences.getString(KERNEL_MD5, "");
                File kernel = new File(kernelFilePath + File.separator + kernelFileName);
                if (!TextUtils.isEmpty(md5) && !TextUtils.isEmpty(downloadUrl)) {
                    if (TextUtils.isEmpty(oldMd5) || !kernel.exists() || !md5.equals(oldMd5)) {
                        downloadUrl = managerServer + downloadUrl;
                        return downloadKernel(downloadUrl, md5);
                    } else {
                        return Flowable.just(true);
                    }
                } else {
                    return Flowable.error(new XCloudException(context.getString(R.string.no_error_config_info)));
                }
            }
        }).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io());
    }

    private Flowable<Boolean> downloadKernel(String url, final String md5) {
        final String tempFileName = "libxwalkcore_temp.so";
        return serviceApi.commonDownload(url).flatMap(new Function<Response<ResponseBody>, Publisher<Boolean>>() {
            @Override
            public Publisher<Boolean> apply(Response<ResponseBody> response) throws Exception {
                int code = response.code();
                if (code == 200) {
                    boolean success = FileUtils.writeToFile(kernelFilePath, tempFileName, response.body().byteStream());
                    if (success) {
                        File newFile = new File(kernelFilePath, tempFileName);
                        File oldFile = new File(kernelFilePath, kernelFileName);
                        if (oldFile.exists()) {
                            boolean b = oldFile.delete();
                        }
                        boolean reNameSuccess = newFile.renameTo(oldFile);
                        if (!reNameSuccess) {
                            return Flowable.error(new XCloudException(context.getString(R.string.kernel_download_error)));
                        } else {
                            return Flowable.just(true);
                        }
                    } else {
                        return Flowable.error(new XCloudException(context.getString(R.string.kernel_download_error)));
                    }
                } else {
                    return Flowable.error(new XCloudException(context.getString(R.string.kernel_request_error) + code));
                }
            }
        }).doOnError(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                File file = new File(kernelFilePath, tempFileName);
                boolean b = file.delete();
                YspLogUtils.d("内核下载失败,异常信息:" + throwable);
            }
        }).doOnNext(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) throws Exception {
                preferences.edit().putString(KERNEL_MD5, md5).apply();
            }
        });
    }
}
